home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Tools / ntail / ntail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  9.0 KB  |  402 lines

  1. /* ntail.c: */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ntail/RCS/ntail.c,v 6.0 1991/12/18 20:32:10 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Tools/ntail/RCS/ntail.c,v 6.0 1991/12/18 20:32:10 jpo Rel $
  9.  *
  10.  * $Log: ntail.c,v $
  11.  * Revision 6.0  1991/12/18  20:32:10  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. /*
  19.  * @(#) ntail.c 2.1 89/07/26 19:15:42
  20.  *
  21.  * Package:    ntail version 2
  22.  * File:    ntail.c
  23.  * Description:    main program
  24.  *
  25.  * Mon Jul 10 02:56:22 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  26.  *    Original composition.
  27.  */
  28.  
  29. #ifndef LINT
  30. static char SCCSID[] = "@(#) ntail.c 2.1 89/07/26 19:15:42";
  31. #endif
  32.  
  33. #include <stdio.h>
  34. #include <signal.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #define  INTERN
  38. #include "ntail.h"
  39.  
  40. #ifdef M_XENIX
  41. # undef  NULL
  42. # define NULL 0
  43. #endif
  44.  
  45.  
  46. int sigcaught = 0;
  47.  
  48. SIGTYPE sigcatcher(sig)
  49. int sig;
  50. {
  51. /*    extern SIGTYPE (*signal)(); */
  52.     if ( sig == SIGQUIT )
  53.     (void) exit(0);
  54.     sigcaught = sig;
  55. #ifdef STATUS_ENAB
  56.     (void) signal(SIGINT,sigcatcher);
  57.     (void) signal(SIGQUIT,sigcatcher);
  58. #endif
  59. }
  60.  
  61.  
  62. main(argc,argv)
  63. int argc;
  64. char *argv[];
  65. {
  66.     int open_files_only, already_open, iteration, i;
  67.     struct entry_descrip *entryp;
  68.     struct stat sbuf;
  69.  
  70.     /* 
  71.      * Initialize.
  72.      */
  73.     List_file.num = 0;
  74.     List_dir.num = 0;
  75.     List_zap.num = 0;
  76.     Sorted = FALSE;
  77.     Reset_status = FALSE;
  78.     Debug = FALSE;
  79.     sigcatcher(0);
  80.  
  81.  
  82.     /*
  83.      * Place all of the entries onto lists.
  84.      */
  85.     for ( i = 1 ; i < argc ; ++i )  {
  86.  
  87.     if ( i == 1 && strcmp(argv[i],"-D") == 0 ) {
  88.         Debug = TRUE;
  89.         continue;
  90.     }
  91.  
  92.     /*
  93.      * Temporarily throw this entry onto the end of the zapped list.
  94.      */
  95.     entryp = new_entry( &List_zap, argv[i] );
  96.  
  97.     /*
  98.      * Stat the file and get it to its proper place.
  99.      */
  100.     switch ( stat_entry( &List_zap, List_zap.num-1, &sbuf ) ) {
  101.  
  102.     case ENTRY_FILE:        /* move entry to file list    */
  103.         move_entry( &List_file, &List_zap, List_zap.num-1 );
  104.         entryp->size = sbuf.st_size;
  105.         entryp->mtime = sbuf.st_mtime;
  106.         break;
  107.  
  108.     case ENTRY_DIR:            /* move entry to dir list    */
  109.         move_entry( &List_dir, &List_zap, List_zap.num-1 );
  110.         entryp->size = sbuf.st_size;
  111.         entryp->mtime = sbuf.st_mtime;
  112.         if ( scan_directory( entryp->name ) != 0 ) {
  113.         message( MSSG_OPEN, entryp );
  114.         rmv_entry( &List_dir, List_dir.num-1 );
  115.         }
  116.         break;
  117.  
  118.     case ENTRY_ZAP:            /* keep entry on zap list    */
  119.         break;
  120.  
  121.     case ENTRY_SPECIAL:        /* entry is a special file    */
  122.         message( MSSG_NOTAFIL, entryp );
  123.         rmv_entry( &List_zap, List_zap.num-1 );
  124.         break;
  125.  
  126.     default:            /* stat error            */
  127.         message( MSSG_STAT, entryp );
  128.         rmv_entry( &List_zap, List_zap.num-1 );
  129.         break;
  130.  
  131.     }
  132.  
  133.     }
  134.  
  135.     /*
  136.      * Make sure we are watching something reasonable.
  137.      */
  138.     if ( List_file.num == 0 ) {
  139.     if ( List_dir.num == 0 && List_zap.num == 0 ) {
  140.         (void) fprintf(stderr, "%s: no valid entries specified\n", argv[0]);
  141.         (void) exit(1);
  142.     }
  143.     (void) puts("\n*** warning - no files are being watched ***");
  144.     }
  145.  
  146.  
  147.     /*
  148.      * From this point on we want to reset the status of an entry any
  149.      * time we move it around to another list.
  150.      */
  151.     Reset_status = TRUE;
  152.  
  153.  
  154.     /*
  155.      * Force a check of everything first time through the loop.
  156.      */
  157.     iteration = CHECK_COUNT;
  158.  
  159.  
  160.     /* 
  161.      * Loop forever.
  162.      */
  163.     for (;;) {
  164.  
  165.     /*
  166.      * Once every CHECK_COUNT iterations check everything.
  167.      * All other times only look at the opened files.
  168.      */
  169.     open_files_only = ( ++iteration < CHECK_COUNT );
  170.     if ( !open_files_only )
  171.         iteration = 0;
  172.  
  173.  
  174.     /*
  175.      * Make sure that the most recently modified files are open.
  176.      */
  177.     if ( !Sorted )
  178.         fixup_open_files();
  179.  
  180.  
  181.     /*
  182.      * Display what we are watching if a SIGINT was caught.
  183.      */
  184.     if ( sigcaught ) {
  185.         show_status();
  186.         sigcatcher(0);
  187.     }
  188.  
  189.  
  190.     /*
  191.      * Go through all of the files looking for changes.
  192.      */
  193.     Dprintf(stderr, ">>> checking files list (%s)\n",
  194.         ( open_files_only ? "open files only" : "all files" ));
  195.     for ( i = 0 ; i < List_file.num ; ++i ) {
  196.  
  197.         entryp = List_file.list[i];
  198.         already_open = ( entryp->fd > 0 ) ;
  199.  
  200.         /*
  201.          * Ignore closed files except every CHECK_COUNT iterations.
  202.          */
  203.         if ( !already_open && open_files_only )
  204.         continue;
  205.  
  206.         /*
  207.          * Get the status of this file.
  208.          */
  209.         switch ( stat_entry( &List_file, i, &sbuf ) ) {
  210.         case ENTRY_FILE:        /* got status OK        */
  211.         break;
  212.         case ENTRY_DIR:        /* huh??? it's now a dir    */
  213.         move_entry( &List_dir, &List_file, i-- );
  214.         continue;
  215.         case ENTRY_ZAP:        /* entry has been deleted    */
  216.         message( MSSG_ZAPPED, entryp );
  217.         move_entry( &List_zap, &List_file, i-- );
  218.         continue;
  219.         case ENTRY_SPECIAL:        /* entry is a special file    */
  220.         message( MSSG_NOTAFIL, entryp );
  221.         rmv_entry( &List_file, i-- );
  222.         continue;
  223.         default:            /* stat error            */
  224.         message( MSSG_STAT, entryp );
  225.         rmv_entry( &List_file, i-- );
  226.         continue;
  227.         }
  228.  
  229.  
  230.         /*
  231.          * See if an opened file has been deleted.
  232.          */
  233.         if ( already_open && sbuf.st_nlink == 0 ) {
  234.         message( MSSG_ZAPPED, entryp );
  235.         move_entry( &List_zap, &List_file, i-- );
  236.         continue;
  237.         }
  238.  
  239.         /*
  240.          * If nothing has changed then continue on.
  241.          */
  242.         if ( entryp->size==sbuf.st_size && entryp->mtime==sbuf.st_mtime )
  243.         continue;
  244.  
  245.         /*
  246.          * If the file isn't already open, then do so.
  247.          *   Note -- it is important that we call "fixup_open_files()"
  248.          *   at the end of the loop to make sure too many files don't
  249.          *   stay opened.
  250.          */
  251.         if ( !already_open && open_entry( &List_file, i ) != 0 ) {
  252.         --i;
  253.         continue;
  254.         }
  255.  
  256.         /*
  257.          * See if the file has been truncated.
  258.          */
  259.         if ( sbuf.st_size < entryp->size ) {
  260.         message( MSSG_TRUNC, entryp );
  261.         entryp->size = 0;
  262.         }
  263.  
  264.         /*
  265.          * Seek to where the changes begin.
  266.          */
  267.         {
  268.         extern long lseek();
  269.         if ( lseek( entryp->fd, entryp->size, 0 ) < 0 ) {
  270.             message( MSSG_SEEK, entryp );
  271.             rmv_entry( &List_file, i-- );
  272.             continue;
  273.         }
  274.         }
  275.  
  276.         /*
  277.          * Dump the recently added info.
  278.          */
  279.         {
  280.         int nb;
  281.             static char buf[BUFSIZ];
  282.         message( MSSG_BANNER, entryp );
  283.         while ( ( nb = read( entryp->fd, buf, sizeof(buf) ) ) > 0 ) {
  284.             (void) fwrite( buf, sizeof(char), (unsigned) nb, stdout );
  285.             entryp->size += nb;
  286.         }
  287.         if ( nb < 0 ) {
  288.             message( MSSG_READ, entryp );
  289.             rmv_entry( &List_file, i-- );
  290.             continue;
  291.         }
  292.         }
  293.  
  294.         /*
  295.          * Update the modification time.
  296.          */
  297.         entryp->mtime = sbuf.st_mtime;
  298.  
  299.         /*
  300.          * Since we've changed the mtime, the list might no longer be
  301.          * sorted.  However if this entry is already at the top of the
  302.          * list then it's OK.
  303.          */
  304.         if ( i != 0 )
  305.         Sorted = FALSE;
  306.  
  307.         /*
  308.          * If we've just opened the file then force a resort now to
  309.          * prevent too many files from being opened.
  310.          */
  311.         if ( !already_open )
  312.         fixup_open_files();
  313.  
  314.     }
  315.  
  316.  
  317.     /*
  318.      * Go through list of nonexistent entries to see if any have appeared.
  319.      *   This is done only once every CHECK_COUNT iterations.
  320.      */
  321.     if ( !open_files_only ) {
  322.         Dprintf(stderr, ">>> checking zapped list\n");
  323.         for ( i = 0 ; i < List_zap.num ; ++i ) {
  324.         entryp = List_zap.list[i];
  325.         switch ( stat_entry( &List_zap, i, &sbuf ) ) {
  326.         case ENTRY_FILE:    /* entry has appeared as a file    */
  327.             message( MSSG_CREATED, entryp );
  328.             move_entry( &List_file, &List_zap, i-- );
  329.             break;
  330.         case ENTRY_DIR:        /* entry has appeared as a dir    */
  331.             message( MSSG_CREATED, entryp );
  332.             move_entry( &List_dir, &List_zap, i-- );
  333.             break;
  334.         case ENTRY_ZAP:        /* entry still doesn't exist    */
  335.             break;
  336.         case ENTRY_SPECIAL:    /* entry is a special file    */
  337.             message( MSSG_NOTAFIL, entryp );
  338.                 rmv_entry( &List_zap, i-- );
  339.             break;
  340.         default:        /* error - entry removed    */
  341.                 message( MSSG_STAT, entryp );
  342.                 rmv_entry( &List_zap, i-- );
  343.             break;
  344.         }
  345.         }
  346.     }
  347.  
  348.  
  349.     /*
  350.      * Go through the list of dirs to see if any new files were created.
  351.      *   This is done only once every CHECK_COUNT iterations.
  352.      */
  353.     if ( !open_files_only ) {
  354.         Dprintf(stderr, ">>> checking directory list\n");
  355.         for ( i = 0 ; !open_files_only && i < List_dir.num ; ++i ) {
  356.         entryp = List_dir.list[i];
  357.         switch ( stat_entry( &List_dir, i, &sbuf ) ) {
  358.         case ENTRY_DIR:        /* got status OK        */
  359.             break;
  360.         case ENTRY_FILE:    /* huh??? it's now a reg file    */
  361.             move_entry( &List_file, &List_dir, i-- );
  362.             continue;
  363.         case ENTRY_ZAP:        /* entry has been deleted    */
  364.                 message( MSSG_ZAPPED, entryp );
  365.                 move_entry( &List_zap, &List_dir, i-- );
  366.             continue;
  367.         case ENTRY_SPECIAL:    /* entry is a special file    */
  368.             message( MSSG_NOTAFIL, entryp );
  369.             rmv_entry( &List_dir, i-- );
  370.             continue;
  371.         default:        /* stat error            */
  372.             message( MSSG_STAT, entryp );
  373.             rmv_entry( &List_dir, i-- );
  374.             continue;
  375.         }
  376.         if ( entryp->mtime == sbuf.st_mtime )
  377.             continue;
  378.         if ( scan_directory( entryp->name ) != 0 ) {
  379.             message( MSSG_OPEN, entryp );
  380.             rmv_entry( &List_dir, i-- );
  381.         }
  382.         entryp->mtime = sbuf.st_mtime;
  383.         }
  384.     }
  385.  
  386.  
  387.     /*
  388.      * End of checking loop.
  389.      */
  390.     {
  391.         extern unsigned sleep();
  392.         (void) fflush(stdout);
  393.         (void) sleep(SLEEP_TIME);
  394.     }
  395.  
  396.     }
  397.  
  398.     /*NOTREACHED*/
  399.  
  400. }
  401.  
  402.